package cl.tinet.trainee.salas.web.mb;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

import org.primefaces.context.RequestContext;

import cl.tinet.trainee.salas.ejb.UsuarioBeanInterfaz;
import cl.tinet.trainee.salas.model.Usuario;
import cl.tinet.trainee.salas.model.excepciones.GeneralException;
import cl.tinet.trainee.salas.model.excepciones.UsuarioContieneReservas;
import cl.tinet.trainee.salas.model.excepciones.UsuarioInactivoException;
import cl.tinet.trainee.salas.model.excepciones.UsuarioNoExisteException;
import cl.tinet.trainee.salas.model.excepciones.UsuarioPasswordExcepction;

/**
 * Managed Bean que manejara las instruccion del usuario.
 * 
 * @author Naht-Sams
 */
@ManagedBean(name = "UsuarioMB")
@SessionScoped
public class UsuarioMB implements Serializable {
    /**
     * Version Serial.
     */
    private static final long serialVersionUID = 1L;
    /**
     * Bean usuario.
     */
    @EJB(mappedName = "UsuarioBean", name = "UsuarioBean")
    private transient UsuarioBeanInterfaz bean;
    /**
     * Instancia objeto tipo usuario.
     */
    private Usuario usuario;
    /**
     * Guardar datos del usuario que entra a la apliacion.
     */
    private Usuario usuarioIniciado;
    /**
     * Lista de usuarios que existen en el sistema.
     * 
     */
    List<Usuario> usuarios;
    /**
     * Mensaje que se despliega en la vista. Si no proviene de una excepcion.
     */
    private String msgError;

    /**
     * 
     * Inicializar el objeto usuario.
     * 
     */
    @PostConstruct
    public void init() {
        usuario = new Usuario();
    }

    /**
     * Metodo verificar si el usuario existe en el sistema.
     * 
     * @return Devuelve la direccion.
     */
    public String verificarUsuario() {
        // Bean buscar datos usuario existente.
        try {
            this.usuarioIniciado = bean.buscarUsuarioBean(this.usuario);
            if (this.usuarioIniciado.getTipoUsuario() == 0) {
                return "mainAdministrador";
            } else if (usuarioIniciado.getTipoUsuario() == 1) {
                this.usuario = usuarioIniciado;
                return "mainNormal?faces-redirect=true";
            }
        } catch (UsuarioNoExisteException e) {
            saveMessage(e.getMessage());
            limpiar();
            return "index";
        } catch (UsuarioInactivoException e) {
            saveMessage(e.getMessage());
            limpiar();
            return "index";
        } catch (UsuarioPasswordExcepction e) {
            saveMessage(e.getMessage());
            limpiar();
            return "index";
        } catch (GeneralException e) {
            return "index";
        }
        return msgError;

    }

    /**
     * Recivir los datos de un usuario, luego se procede hacer una busqueda
     * dentoro de la BD, si esque lo encuentra lo recive una exception la cual
     * envia un mensaje de error. En el caso contrario se agrega el dato en la
     * BD.
     * 
     * @throws UsuarioException
     */
    public void crearUsuario() {
        try {
            bean.buscarUsuarioAgregado(this.usuario);
            bean.agregarUsuarioBean(this.usuario);
            saveMessage("Usuario Ingresado", this.usuario);
            this.usuario = null;
            RequestContext.getCurrentInstance().execute(
                    "PF('dAgregarUsuario').hide()");
        } catch (GeneralException e) {
            saveMessage(e.getMessage(), this.usuario);
        }
        desplegarUsuarios();
    }

    /**
     * Buscar los datos del usuario que se este intentando eliminar.
     * 
     * @param usuarioRecivido
     *            Datos del usuario recivido.
     * @return Devuelve la direccion luego de encontrar el usuario.
     */
    public String buscarEliminarUsuario(Usuario usuarioRecivido) {
        this.usuario = usuarioRecivido;
        return "eliminarDatosUsuario";
    }

    /**
     * Proceder a eliminar un usuario de la base de datos. Validando que la
     * password ingresada sea igual.
     * @param usuarioRecivido Datos del usuario a eliminar.
     */
    public String eliminarUsuarioNormal() {
        eliminarUsuario(usuarioIniciado);
        return logout();
    }
    
    /**
     * Proceder a eliminar un usuario de la base de datos. Validando que la
     * password ingresada sea igual.
     * @param usuarioRecivido Datos del usuario a eliminar.
     */
    public void eliminarUsuario(Usuario usuarioRecivido) {
        this.usuario = usuarioRecivido;
        try {
            bean.eliminarUsuarioBean(usuarioRecivido);
            this.msgError = "Usuario Eliminado";
            saveMessage(this.msgError, this.usuario);
            this.usuarios = null;
            desplegarUsuarios();
        } catch (UsuarioContieneReservas e) {
            // Logger
            this.msgError = "Usuario no eliminado. Contiene reservas.";
            saveMessage(this.msgError, this.usuario);
        }
    }

    /**
     * 
     * Invalidar las sessiones del sistema.
     *
     * @return direcciona principal.
     */
    public String logout() {
        HttpSession session =
                (HttpSession) FacesContext.getCurrentInstance()
                        .getExternalContext().getSession(false);
        session.invalidate();
        return "index";
    }

    /**
     * Buscar los datos de un usuario que se desea modificar.
     * 
     * @param usuarioRecivido
     *            Datos del usuario seleccionado
     */
    public void buscarModificarUsuario(Usuario usuarioRecivido) {
        this.usuario = usuarioRecivido;
        org.primefaces.context.RequestContext.getCurrentInstance().update(
                "fModificarUsuario:pModificarUsuario");
    }
    /**
     * 
     * Modificar usuario de tipo normal.
     *
     */
    public String modificarUsuarioNormal(){
        this.usuario = usuarioIniciado;
        modificarUsuario();
        return "mainNormal";
    }
    
    /**
     * Proceder a modificar los datos del usuario. Luego dejo el objeto que se
     * encuentra en session vacio.
     * 
     */
    public void modificarUsuario() {
        bean.modificarUsuarioBean(this.usuario);
        this.msgError = "Usuario Modificado";
        saveMessage(this.msgError, this.usuario);
        RequestContext.getCurrentInstance().execute(
                "PF('dModificarUsuario').hide()");
        this.usuarios = null;
        desplegarUsuarios();
    }

    /**
     * 
     * Limpiar datos objeto.
     * 
     */
    public void limpiar() {
        this.usuario = new Usuario();
    }

    /**
     * Allows to get the usuario attribute value.
     * 
     * @return the usuario value.
     */
    public final Usuario getUsuario() {
        return usuario;
    }

    /**
     * Allows to set the usuario attribute value.
     * 
     * @param usuario
     *            new value for usuario attribute.
     */
    public final void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    /**
     * Allows to get the usuarios attribute value.
     * 
     * @return the usuarios value.
     */
    public List<Usuario> getUsuarios() {
        return usuarios;
    }

    /**
     * Allows to set the usuarios attribute value.
     * 
     * @param usuarios
     *            new value for usuarios attribute.
     */
    public void setUsuarios(List<Usuario> usuarios) {
        this.usuarios = usuarios;
    }

    /**
     * Allows to get the usuarioIniciado attribute value.
     * 
     * @return the usuarioIniciado value.
     */
    public Usuario getUsuarioIniciado() {
        return usuarioIniciado;
    }

    /**
     * Allows to set the usuarioIniciado attribute value.
     * 
     * @param usuarioIniciado
     *            new value for usuarioIniciado attribute.
     */
    public void setUsuarioIniciado(Usuario usuarioIniciado) {
        this.usuarioIniciado = usuarioIniciado;
    }

    /**
     * Buscar la lista completo e usuarios y dejalos en una lista.
     */
    public void desplegarUsuarios() {
        this.usuarios = bean.buscarUsuarios();
        if (this.usuarios.isEmpty()) {
            usuario.setUsername("-");
            saveMessage("No usuarios registrados.", usuario);
        }
    }

    /**
     * Allows to get the msgError attribute value.
     * 
     * @return the msgError value.
     */
    public String getMsgError() {
        return msgError;
    }

    /**
     * Allows to set the msgError attribute value.
     * 
     * @param msgError
     *            new value for msgError attribute.
     */
    public void setMsgError(String msgError) {
        this.msgError = msgError;
    }

    /**
     * Growl.
     * 
     * @param msg
     *            Se entrega el string de msg.
     * @param usuario
     *            Usuario a mostrar.
     */
    public static void saveMessage(String msg, Usuario usuario) {
        RequestContext.getCurrentInstance().update("miform");
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage("gfMessages",
                new FacesMessage(FacesMessage.SEVERITY_ERROR, "Alerta", ""
                        + msg + "(" + usuario.getUsername() + ")"));
    }

    /**
     * Growl.
     * 
     * @param msg
     *            Se entrega el string de msg.
     */
    public static void saveMessage(String msg) {
        RequestContext.getCurrentInstance().update("miform");
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage("gfMessages", new FacesMessage(
                FacesMessage.SEVERITY_ERROR, "Alerta", "" + msg));
    }

}
